package com.example.fastshare.adapter;

import java.io.File;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;

import com.example.fastshare.entities.GroupEntity;
import com.example.fastshare.entities.ImageEntity;
import com.example.fastshare.entities.MessageEntity;
import com.example.fastshare.entities.UserEntity;

public class DatabaseAdapter {

	private static final String CREATE_IMAGE_TABLE = "CREATE TABLE IF NOT EXISTS "
			+ ImageEntity.TABLE_NAME
			+ " ("
			+ ImageEntity.ID
			+ " TEXT PRIMARY KEY NOT NULL, "
			+ ImageEntity.PATH
			+ " TEXT, "
			+ ImageEntity.NAME + " TEXT, " + ImageEntity.USER_ID + " TEXT )";

	private static final String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS "
			+ UserEntity.TABLE_NAME
			+ " ("
			+ UserEntity.ID
			+ " TEXT PRIMARY KEY NOT NULL, "
			+ UserEntity.NAME
			+ " TEXT, "
			+ UserEntity.AVATAR_PATH + " TEXT )";

	private static final String CREATE_GROUP_TABLE = "CREATE TABLE IF NOT EXISTS "
			+ GroupEntity.TABLE_NAME
			+ " ("
			+ GroupEntity.ID
			+ " TEXT PRIMARY KEY NOT NULL, "
			+ GroupEntity.NAME
			+ " TEXT, "
			+ GroupEntity.DESCRIPTION
			+ " TEXT, "
			+ GroupEntity.ICON_PATH
			+ " TEXT )";

	// FIXME ------ DATABSE FIELD MISSING

	private static final String CREATE_MESSAGE_TABLE = "CREATE TABLE IF NOT EXISTS "
			+ MessageEntity.TABLE_NAME
			+ " ("
			+ MessageEntity.ID
			+ " TEXT PRIMARY KEY NOT NULL, "
			+ MessageEntity.USER_ID
			+ " TEXT, "
			+ MessageEntity.GROUP_ID
			+ " TEXT, "
			+ MessageEntity.IMAGE_ID
			+ " TEXT, "
			+ MessageEntity.MESSAGE_TYPE
			+ " TEXT, "
			+ MessageEntity.CONTENT
			+ " TEXT, "
			+ MessageEntity.TIME + " TEXT )";

	private static final String DATABASE_FILE_PATH = Environment
			.getExternalStorageDirectory().toString() + "/fastshare/database";
	private static final String DATABASE_NAME = "data.db";
	private static SQLiteDatabase mDatabase;

	public DatabaseAdapter(Context context) {
		Log.d("DBtest",
				"External Storage Stage: "
						+ Environment.getExternalStorageState());
		Log.d("DBtest",
				"External Storage Directory: "
						+ Environment.getExternalStorageDirectory());
		Log.d("DBtest", "Database Directory: " + DATABASE_FILE_PATH);
		Log.d("DBtest", "Start to create DB");
		Log.d("DBtest", "Is database: " + databaseExist());
		File appDbDir = new File(DATABASE_FILE_PATH);

		if (!appDbDir.exists()) {
			appDbDir.mkdirs();
			Log.d("DBtest", "Maked Dir");
		}

		Log.d("DBtest", "Directory checking is completed");
		if (mDatabase == null) {
			Log.d("DBtest", "Get readable + writable DB");
			mDatabase = getReadableWritableDatabase();
			// Create tables
			onCreate();
			Log.d("DBtest", "Database Created");
		}
		Log.d("DBtest", "Constructor is finished.");

	}

	public boolean databaseExist() {
		File dbFile = new File(DATABASE_FILE_PATH + "/" + DATABASE_NAME);
		return dbFile.exists();
	}

	/**
	 * Convenience method for inserting a row into the database.
	 * 
	 * @param table
	 *            The table to insert the row into
	 * @param nullColumnHack
	 *            SQL doesn't allow inserting a completely empty row, so if
	 *            initialValues is empty this column will explicitly be assigned
	 *            a NULL value
	 * @param values
	 *            this map contains the initial column values for the row. The
	 *            keys should be the column names and the values the column
	 *            values
	 * @return the row ID of the newly inserted row, or -1 if an error occurred
	 */
	public long insert(String table, String nullColumnHack, ContentValues values) {
		long result = mDatabase.insert(table, nullColumnHack, values);
		return result;
	}

	/**
	 * Convenience method for updating rows in the database.
	 * 
	 * @param table
	 *            the table to update in
	 * @param values
	 *            a map from column names to new column values. null is a valid
	 *            value that will be translated to NULL.
	 * @param whereClause
	 *            the optional WHERE clause to apply when updating. Passing null
	 *            will update all rows.
	 * @param whereArgs
	 * @return the number of rows affected
	 */
	public int update(String table, ContentValues values, String whereClause,
			String[] whereArgs) {
		int result = mDatabase.update(table, values, whereClause, whereArgs);
		return result;
	}

	/**
	 * Convenience method for deleting rows in the database.
	 * 
	 * @param table
	 *            the table to delete from
	 * @param whereClause
	 *            the optional WHERE clause to apply when deleting. Passing null
	 *            will delete all rows.
	 * @param whereArgs
	 * @return the number of rows affected if a whereClause is passed in, 0
	 *         otherwise. To remove all rows and get a count pass "1" as the
	 *         whereClause.
	 */
	public int delete(String table, String whereClause, String[] whereArgs) {
		int result = mDatabase.delete(table, whereClause, whereArgs);
		return result;
	}

	public Cursor query(String table, String[] columns, String selection,
			String[] selectionArgs, String groupBy, String having,
			String orderBy) {
		Cursor cur = mDatabase.query(table, columns, selection, selectionArgs,
				groupBy, having, orderBy);
		if (cur != null) {
			cur.moveToFirst();
		}
		return cur;
	}

	public Cursor query(String table, String[] columns, String selection,
			String[] selectionArgs, String groupBy, String having,
			String orderBy, String limit) {
		Cursor cur = mDatabase.query(table, columns, selection, selectionArgs,
				groupBy, having, orderBy, limit);
		if (cur != null) {
			cur.moveToFirst();
		}
		return cur;
	}

	public Cursor query(boolean distinct, String table, String[] columns,
			String selection, String[] selectionArgs, String groupBy,
			String having, String orderBy, String limit) {
		Cursor cur = mDatabase.query(distinct, table, columns, selection,
				selectionArgs, groupBy, having, orderBy, limit);
		if (cur != null) {
			cur.moveToFirst();
		}
		return cur;
	}

	public Cursor rawQuery(String sql, String[] selectionArgs) {
		Cursor cur = mDatabase.rawQuery(sql, selectionArgs);
		if (cur != null) {
			cur.moveToFirst();
		}
		return cur;
	}

	public void execSQL(String sql) throws SQLException {
		mDatabase.execSQL(sql);
	}

	public void execSQL(String sql, Object[] bindArgs) throws SQLException {
		mDatabase.execSQL(sql, bindArgs);
	}

	public void onCreate() {
		Log.d("DBtest", "Start to execute sql");
		mDatabase.execSQL(CREATE_USER_TABLE);
		mDatabase.execSQL(CREATE_IMAGE_TABLE);
		mDatabase.execSQL(CREATE_GROUP_TABLE);
		mDatabase.execSQL(CREATE_MESSAGE_TABLE);
		Log.d("DBtest", "Sql executed");
	}

	public void onUgrade() {
		mDatabase.execSQL("DROP TABLE IF EXISTS " + UserEntity.TABLE_NAME);
		mDatabase.execSQL("DROP TABLE IF EXISTS " + ImageEntity.TABLE_NAME);
		mDatabase.execSQL("DROP TABLE IF EXISTS " + GroupEntity.TABLE_NAME);
		mDatabase.execSQL("DROP TABLE IF EXISTS " + MessageEntity.TABLE_NAME);

	}

	public void close() {
		if (mDatabase != null) {
			mDatabase.close();
			mDatabase = null;
		}
	}

	public SQLiteDatabase getReadableWritableDatabase() {
		SQLiteDatabase db = SQLiteDatabase.openDatabase(DATABASE_FILE_PATH
				+ File.separator + DATABASE_NAME, null,
				SQLiteDatabase.OPEN_READWRITE
						+ SQLiteDatabase.CREATE_IF_NECESSARY);
		return db;
	}

	public SQLiteDatabase getInstanceDataBase() {
		return mDatabase;
	}

}